package com.wolfstreet.wsonline.http;

import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.wolfstreet.wsonline.R;
import com.wolfstreet.wsonline.bean.JumpRunnable;
import com.wolfstreet.wsonline.bean.UserInfo;
import com.wolfstreet.wsonline.util.DialogUtil;
import com.wolfstreet.wsonline.util.JsonUtil;
import com.wolfstreet.wsonline.util.LoadDialog;
import com.wolfstreet.wsonline.util.SPUtil;
import com.wolfstreet.wsonline.util.ThreadPoolUtil;

public class HttpHelper {
	/**
	 * CONNECTION_FAILED 联网失败
	 * 
	 * @author Desmond 2014-11-5 下午3:38:32
	 */
	public static final int CONNECTION_FAILED = -100;

	/**
	 * CONNECTION_TIMEOUT 超时
	 * 
	 * @author Desmond 2014-11-5 下午4:02:55
	 */
	public static final int CONNECTION_TIMEOUT = -400;

	/**
	 * BAD_JSON 格式错误
	 * 
	 * @author Desmond 2014-11-5 下午4:02:55
	 */
	public static final int BAD_JSON = -500;

	/**
	 * DATA_FAILED 数据解析失败
	 * 
	 * @author Desmond 2014-11-5 下午3:38:40
	 */
	public static final int DATA_FAILED = -200;

	/**
	 * OTHOR_ERROR 其他错误
	 * 
	 * @author Desmond 2014-11-5 下午3:39:31
	 */
	public static final int OTHOR_ERROR = -300;

	protected static DialogUtil dialogUtil;
	// protected static ProgressDialog lodding;
	private static LoadDialog loading;

	public static final int TIMEOUT_SECOND = 10000;

	public static final int SOCKET_SECOND = 15000;

	public static final int LOGOUT_CODE = 304;

	public static final int ANOTHER_CODE = 305;

	/**
	 * SUCCESS 请求成功
	 * 
	 * @author Desmond 2014-11-5 下午3:58:45
	 */
	public static final int SUCCESS = 0;

	/**
	 * 发送请求
	 * 
	 * @param url
	 *            请求路径
	 * @param paramList
	 *            参数键值对list
	 * @param listener
	 *            监听器
	 * @param id
	 *            请求的id
	 * @param isShow
	 *            是否显示加载小圈圈
	 */
	public static void send(final String url, final JSONObject json,
			final HttpResponseListener listener, final int id,
			final boolean isShow) {
		if (isShow) {
			if (listener instanceof Activity) {
				loading = new LoadDialog((Activity) listener,
						R.style.dialog_style);
				loading.show();
			}
		}
		// 添加等待框 yu_ruizhe 20141031 end
		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				executeResponse(msg, listener);
			}
		};
		ThreadPoolUtil.HTTP_THREAD_POOL.submit(new Runnable() {
			@Override
			public void run() {
				Http http = null;
				// 创建连接
				HttpParams httpParams = new BasicHttpParams();
				// 设置连接超时
				HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_SECOND);
				// 设置socket超时
				HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_SECOND);
				// 获取HttpClient对象 （认证）
				DefaultHttpClient httpClient = initHttpClient(httpParams);
				httpClient.getParams()
						.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
								TIMEOUT_SECOND);
				httpClient.getParams().setParameter(
						CoreConnectionPNames.SO_TIMEOUT, SOCKET_SECOND);
				httpClient.getParams().setParameter(
						CoreConnectionPNames.SO_TIMEOUT, TIMEOUT_SECOND);
				HttpPost post = new HttpPost(url);
				String result = "";
				try {
					List<NameValuePair> valueList = new ArrayList<NameValuePair>();
					JSONObject dataJson = new JSONObject();
					JSONObject headerJson = new JSONObject();
					// UserInfo userInfo = SPUtil.get((Context) listener,
					// SPUtil.USER_INFO);
					String loginStr = SPUtil.get((Context) listener,
							SPUtil.USER_INFO);
					if (loginStr != null && loginStr.length() > 0) {
						UserInfo userInfo = JsonUtil.json2Entity(loginStr,
								UserInfo.class);
						String token = SPUtil.get((Context) listener,
								SPUtil.TOKEN);
						json.put("type", "s");
						json.put("token", token);
						json.put("id", userInfo.getId());
					}
					if (id == HttpParam.ID.UPLOAD_IMG) {
						MultipartEntity entity = new MultipartEntity();

						Iterator iter = json.keys();
						while (iter.hasNext()) {
							String key = iter.next().toString();
							if (key.equals("attachment")) {
								File file = new File(json
										.getString("attachment"));
								ContentBody contentBody = new FileBody(file);
								entity.addPart(key, contentBody);
								continue;
							}
							BasicNameValuePair pair = new BasicNameValuePair(
									key, json.getString(key));
							ContentBody contentBody = new StringBody(pair
									.getValue());
							entity.addPart(pair.getName(), contentBody);
						}

						// entity.addPart(name, contentBody);
						post.setEntity(entity);
						// post.addHeader("Content-Type", "application/json");
					} else {
						post.setEntity(new StringEntity(json.toString(),
								"utf-8"));
						post.addHeader("Content-Type", "application/json");
					}

					// post.setEntity(new UrlEncodedFormEntity(valueList,
					// "utf-8"));
					// 发送HttpPost请求，并返回HttpResponse对象
 					HttpResponse httpResponse = httpClient.execute(post);
					if (loading != null) {
						loading.dismiss();
					}
					// 判断请求响应状态码，状态码为200表示服务端成功响应了客户端的请求
					if (httpResponse.getStatusLine().getStatusCode() == 200) {
						// 获取返回结果
						result = EntityUtils.toString(httpResponse.getEntity());
					} else {
						http = new Http(result, CONNECTION_FAILED, "网络链接失败");
					}
				} catch (HttpHostConnectException e1)// 网络链接失败
				{
					http = new Http(result, CONNECTION_FAILED, "网络链接失败");
				} catch (ConnectTimeoutException e2)// 超时
				{
					http = new Http(result, CONNECTION_TIMEOUT, "请求超时");
				} catch (Exception e) {
					// 其他错误·
					http = new Http(result, OTHOR_ERROR, "网络链接失败");
				} finally {
					if (http == null) {
						http = new Http(result, SUCCESS, "成功");
						JSONObject json;
						try {
							json = new JSONObject(result);
							if (json != null) {
								int code = json.getInt("code");
								String msg = json.getString("msg");
								String data = json.getString("data");
								if (code == SUCCESS) {
									http = new Http(data, SUCCESS, msg);
								} else {
									if (code == 305) {
										Context context = (Context) listener;
										SPUtil.save(context,
												SPUtil.LOGIN_STATUS, "");
										SPUtil.save(context, SPUtil.USER_INFO,
												"");
										JumpRunnable runnable = new JumpRunnable(
												context);
										handler.post(runnable);
									}
									http = new Http(data, code, msg);
								}
							}
						} catch (Exception e1) {
							http = new Http(result, BAD_JSON, "网络连接失败");
						}
					}
					// 通知ui线程
					Message message = handler.obtainMessage();
					message.obj = http;
					message.what = id;
					message.sendToTarget();
				}
			}
		});
	}


	/**
	 * 初始化HttpClient对象
	 * 
	 * @param params
	 * @return
	 */
	public static synchronized DefaultHttpClient initHttpClient(
			HttpParams params) {
		try {
			KeyStore trustStore = KeyStore.getInstance(KeyStore
					.getDefaultType());
			trustStore.load(null, null);

			SSLSocketFactory sf = new SSLSocketFactoryImp(trustStore);
			// 允许所有主机的验证
			sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

			HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
			HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
			// 设置http和https支持
			SchemeRegistry registry = new SchemeRegistry();
			registry.register(new Scheme("http", PlainSocketFactory
					.getSocketFactory(), 80));
			registry.register(new Scheme("https", sf, 443));

			ClientConnectionManager ccm = new ThreadSafeClientConnManager(
					params, registry);
			DefaultHttpClient client = new DefaultHttpClient(ccm, params);
			return client;
		} catch (Exception e) {
			Log.e("asd", e.toString());
			Log.d("asd", e.toString());
			e.printStackTrace();
			System.out.println(e.toString());
			return new DefaultHttpClient(params);
		}
	}

	/**
	 * Post请求连接Https服务
	 * 
	 * @param serverURL
	 *            请求地址
	 * @param jsonStr
	 *            请求报文
	 * @return
	 * @throws Exception
	 */
	public static synchronized String doHttpsPost(String serverURL,
			String jsonStr) throws Exception {
		// 参数
		HttpParams httpParameters = new BasicHttpParams();
		// 设置连接超时
		HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
		// 设置socket超时
		HttpConnectionParams.setSoTimeout(httpParameters, 3000);
		// 获取HttpClient对象 （认证）
		HttpClient hc = initHttpClient(httpParameters);
		HttpPost post = new HttpPost(serverURL);
		// 发送数据类型
		post.addHeader("Content-Type", "application/json;charset=utf-8");
		// 接受数据类型
		post.addHeader("Accept", "application/json");
		// 请求报文
		StringEntity entity = new StringEntity(jsonStr, "UTF-8");
		post.setEntity(entity);
		post.setParams(httpParameters);
		HttpResponse response = null;
		try {
			response = hc.execute(post);
		} catch (UnknownHostException e) {
			throw new Exception("Unable to access " + e.getLocalizedMessage());
		} catch (SocketException e) {
			e.printStackTrace();
		}
		int sCode = response.getStatusLine().getStatusCode();
		if (sCode == HttpStatus.SC_OK) {
			return EntityUtils.toString(response.getEntity());
		} else
			throw new Exception("StatusCode is " + sCode);
	}

	public static class SSLSocketFactoryImp extends SSLSocketFactory {
		final SSLContext sslContext = SSLContext.getInstance("TLS");

		public SSLSocketFactoryImp(KeyStore truststore)
				throws NoSuchAlgorithmException, KeyManagementException,
				KeyStoreException, UnrecoverableKeyException {
			super(truststore);

			TrustManager tm = new X509TrustManager() {
				public java.security.cert.X509Certificate[] getAcceptedIssuers() {
					return null;
				}

				@Override
				public void checkClientTrusted(
						java.security.cert.X509Certificate[] chain,
						String authType)
						throws java.security.cert.CertificateException {
				}

				@Override
				public void checkServerTrusted(
						java.security.cert.X509Certificate[] chain,
						String authType)
						throws java.security.cert.CertificateException {
				}
			};
			sslContext.init(null, new TrustManager[] { tm }, null);
		}

		@Override
		public Socket createSocket(Socket socket, String host, int port,
				boolean autoClose) throws IOException, UnknownHostException {
			return sslContext.getSocketFactory().createSocket(socket, host,
					port, autoClose);
		}

		@Override
		public Socket createSocket() throws IOException {
			return sslContext.getSocketFactory().createSocket();
		}
	}

	public static void executeResponse(Message msg,
			HttpResponseListener listener) {
		try {
			if (loading != null) {
				loading.dismiss();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		Http http = (Http) msg.obj;
		listener.httpResponse(http.data, http.code, http.msg, msg.what);
	}

	public static String getVersion(Context context) {
		PackageManager manager;

		PackageInfo info = null;

		manager = context.getPackageManager();

		try {

			info = manager.getPackageInfo(context.getPackageName(), 0);

		} catch (NameNotFoundException e) {

			// TODO Auto-generated catch block

			e.printStackTrace();

		}

		int versionCode = info.versionCode;

		String versionName = info.versionName;

		return versionName;

	}

}
